package com.lgrglw.search.dao;

import java.io.IOException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.TermPositionVector;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.TokenSources;


/**
 * 读取索引的抽象方法
 * 
 * @author liwei
 * 
 */
public class IndexReaderOper {

	private static final Log log = LogFactory.getLog(IndexReaderOper.class);
	/**
	 * 默认每页读取的记录数
	 */
	private final static int MAX_SIZE = 30;
	/**
	 * 对命中字符的高亮显示的格式化样式
	 */
	private final static SimpleHTMLFormatter DEFAULT_HIGHLIGHTER_FORMAT = new SimpleHTMLFormatter(
			"<font color='red'><b>", "</b></font>");
	/**
	 * 高亮显示的最大长度
	 */
	private static final SimpleFragmenter DEFAULT_SIMPLE_FRAGMENTER = new SimpleFragmenter(
			150);

	/**
	 * 检索器，基于索引读取器
	 */
	public Searcher searcher;

	/**
	 * 索引读取器
	 */
	public IndexReader reader;

	/**
	 * 查询语句的词间逻辑关系
	 */
	public QueryParser.Operator operator = QueryParser.AND_OPERATOR;

	/**
	 * 允许用户设置命中关键字的高亮显示格式
	 */
	private SimpleHTMLFormatter highlighter = IndexReaderOper.DEFAULT_HIGHLIGHTER_FORMAT;
	/**
	 * 允许用户设置命中关键字的高亮长度
	 */
	private SimpleFragmenter simpleFragmenter = IndexReaderOper.DEFAULT_SIMPLE_FRAGMENTER;

	/**
	 * 解析查询语句
	 * 
	 * @param queryString
	 *            查询语句
	 * @param analyzer
	 *            分词器
	 * @param field
	 *            字段
	 * @return
	 * @throws ParseException
	 */
	public Query parse(String queryString, Analyzer analyzer, String field)
			throws ParseException {
		// 搜索关键词解析
		QueryParser parser = new QueryParser(field, analyzer);
		// 设置查询语句的词间逻辑关系
		parser.setDefaultOperator(operator);
		return parser.parse(queryString);
	}

	/**
	 * 打开索引读取器
	 * 
	 * @param alas
	 */
	public IndexReaderOper(String alas) {
		try {
			reader = IndexReader.open(alas);
			searcher = new IndexSearcher(reader);
		} catch (IOException e) {
			log.error("无法创建索引读取器!", e);
		}
	}

	public void end() {
		try {
			if (searcher != null) {
				searcher.close();
				searcher = null;
			}
			if (reader != null) {
				reader.close();
				reader = null;
			}
		} catch (Exception e) {
			log.error("关闭搜索服务时出错了！", e);
		}

	}

	/**
	 * 得到指定的查询语句的符合条件的字段数目
	 * 
	 * @param queryString
	 * @param analyzer
	 * @param field
	 * @return
	 * @throws ParseException
	 * @throws IOException
	 */
	public int count(String queryString, Analyzer analyzer, String field,
			String alias) throws Exception {
		// 解析查询语句
		Query query = parse(queryString, analyzer, field);
		Hits hits = searcher.search(query);
		return hits.length();
	}

	/**
	 * 搜索方法
	 * 
	 * @return
	 */
	public Hits search(Query query, Sort sort) throws Exception {
		Hits tmpHits = null;
		if (sort != null) {// 有需要排序的字段
			tmpHits = searcher.search(query, sort);
		} else {
			tmpHits = searcher.search(query);
		}
		return tmpHits;
	}

	/**
	 * 创建高亮处理对象，并且进行属性设置
	 * 
	 * @param query
	 *            查询表达式对象
	 * @return
	 */
	public Highlighter create(Query query) {
		Highlighter endHighlighter = new Highlighter(highlighter,
				new QueryScorer(query));
		endHighlighter.setTextFragmenter(simpleFragmenter);
		return endHighlighter;
	}

	/**
	 * 读取查询关键词高亮的最匹配上下文
	 * 
	 * @param highlighter
	 *            高亮处理对象
	 * @param fieldName
	 *            高亮的索引域名称
	 * @param id
	 *            当前符合查询条件的document的id
	 * @param text
	 *            需要高亮的文本
	 * @return 最匹配高亮文本的上下文段落文本
	 * @throws IOException
	 */
	public String getFragment(Highlighter highlighter, String fieldName,
			int id, String text) throws IOException {
		if (StringUtils.isNotBlank(text)) {
			TermPositionVector tpv = (TermPositionVector) reader
					.getTermFreqVector(id, fieldName);
			TokenStream tokenStream = TokenSources.getTokenStream(tpv, true);
			String match = highlighter.getBestFragment(tokenStream, text);
			tokenStream.close();
			return match;
		} else {
			return null;
		}
	}

	public void setHighlighter(String leftTag, String rightTag) {
		this.highlighter = new SimpleHTMLFormatter(leftTag, rightTag);
	}

	public void setSimpleFragmenter(int size) {
		this.simpleFragmenter = new SimpleFragmenter(size);
	}

	public void setOperator(QueryParser.Operator oper) {
		this.operator = oper;
	}

}
